home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / smoke / README < prev    next >
Encoding:
Text File  |  1994-08-02  |  6.7 KB  |  324 lines

  1.   
  2.                 ~4Dgifts/toolbox/src/exampleCode/smoke README
  3.  
  4.             Texture Mapped `smoke' special effects implementation
  5.  
  6.  
  7.  
  8.      to see the demo (with decent results), run the "cmdline" script.
  9.      smokeNoTex is an executable built showing plain polygons (see Makefile).
  10.  
  11.  
  12.  
  13.    the rest of this file is the text portions of the Smoke.sc showcase file:
  14.    -------------------------------------------------------------------------
  15.  
  16.  
  17.     This program started out as a enhancement-request from General Dynamics 
  18.     to Deneb Robotics, for Deneb's factory-floor simulation products.
  19.  
  20.     There were two parts to the request: 
  21.  
  22.     1.  a visualization of the source smoke or plume.
  23.  
  24.     2.  visualizing a compartment filling with smoke according to 
  25.         some rudimentary CFD calculations.
  26.  
  27.     I only focused on step 1, with a pointer to the `pfuSmoke' functionality
  28.     inside our Performer product.
  29.  
  30.     Unfortunately, there were just too many technical hurdles to allow us 
  31.     (myself and the lead gfx programmer at Deneb) to utilize the Performer 
  32.     functionality directly.
  33.  
  34.     So, I took matters into my own hands and peeked in the source...
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.     The Performer utility code I looked at had:
  42.  
  43.  
  44.     1) an algorithm for translating single quad polygons along a direction 
  45.        vector over time while scaling the quad, and decreasing opacity 
  46.        (increasing transparency?)...
  47.  
  48.  
  49. void drawSmoke(uSmoke *smoke, uVec3 eye)
  50. {
  51.     double      now = uGetTime();
  52.     double      deltaTime, age = 1.0f;
  53. ...
  54. /* Compute time elapsed from previous uDrawSmoke */
  55.     if(smoke->prevTime < 0.0f)
  56.         deltaTime = 0.0f;
  57.     else
  58.         deltaTime = now - smoke->prevTime;
  59.  
  60.     if(smoke->duration > 0.0f)
  61.     {
  62.         age = 1.0 - (now - smoke->startTime) / smoke->duration;
  63. ...
  64.     }
  65. ...
  66.     puffInterval = smoke->puffInterval / age;
  67.     puffDiss = smoke->dissipation/smoke->density * age; 
  68.  
  69.     puff->t = (now - puff->startTime) / puffDiss;
  70.  
  71. ...
  72.     puff->transp = puff->t * puff->t * puff->t * puff->t;
  73.       
  74. /* Radius is linear interpolation between radius and expansion */
  75.     puff->radius = (1.0f - puff->transp) * smoke->radius +
  76.     puff->transp * smoke->expansion * smoke->radius
  77. ...
  78. /* Translate puff based on velocity vector */
  79.     tmp = puff->origin;
  80.     uAddVec3(tmp, tmp, dist);
  81. ...
  82.  
  83.     if(smoke->tex) {
  84.         uApplyTex(smoke->tex);
  85.     }
  86.  
  87.  
  88.     drawPuff(puff, smoke, eye);
  89. }
  90.  
  91.  
  92. void uApplyTex(uTexture *tex)
  93. {
  94.     if(tex == NULL)
  95.     {
  96.         fprintf(stderr,"uApplyTex() Null uTexture.\n");
  97.         return;
  98.     }
  99.     texbind(TX_TEXTURE_0, tex->index);
  100. }
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.     2) code to cause all the quads to be rotated to face the eye-point in 
  108.        world coordinate space...
  109.  
  110.  
  111. void drawPuff(uPuff *puff, uSmoke *smoke, uVec3 eye)
  112. {
  113. ...
  114.  /*
  115.   * Compute matrix which rotates puff to face the eyepoint
  116.   */
  117.   uSubVec3(toEye, eye, puff->origin);
  118.  
  119.   uMakeRotOntoMat(mat, vec, toEye);
  120.  
  121.   for(i=0; i<4; i++)
  122.   {
  123.      uVec3           svert;
  124.  
  125.    /* Scale quad to current radius */
  126.      uScaleVec3(svert, puff->radius, quad[i]);
  127.  
  128.    /* Offset puff based on radius */
  129.      svert[1] -= smoke->radius;
  130.  
  131.    /* Rotate puff to follow viewer */
  132.      uXformPt3(dquad[i], svert, mat);
  133.  
  134.    /* Translate puff to origin */
  135.      uAddVec3(dquad[i], dquad[i], puff->origin);
  136.  
  137.   }
  138. ...
  139. }
  140.  
  141. ***I know this part can and should be done by our hardware;  I just haven't
  142.    had time to finish the change.
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.     3) a texture map with alpha-channel that would be modulated with the 
  150.        alpha value of the quad.
  151.  
  152.  
  153. void drawPuff(uPuff *puff, uSmoke *smoke, uVec3 eye)
  154. {
  155.     uVec4       opaque;
  156.     long        i;
  157. ...
  158. #define Zv 0.0
  159. static float t2[]={1,0,Zv,1,1,Zv,0,1,Zv,0,0,Zv};
  160. ...
  161. uAddScaledVec3(opaque, smoke->bgnColor, puff->t, smoke->deltaColor);
  162.  
  163. opaque[3] = 1.0f - puff->transp;
  164.  
  165. ...
  166. #if NOTEXTURE
  167.         #define T2F(t)
  168. #else
  169.         #define T2F(t)  t2f((t))
  170. #endif
  171.  
  172. /*Draw a puff...finally*/
  173.     lmcolor(LMC_DIFFUSE);
  174.     c4f(opaque);
  175.     bgnpolygon();
  176.         cross(dquad[0],dquad[1],dquad[2],&norm[0],&norm[1],&norm[2]);
  177.         norm_d[0]=(dquad[0][0]-norm[0]);
  178.         norm_d[1]=(dquad[0][1]-norm[1]);
  179.         norm_d[2]=(dquad[0][2]-norm[2]);
  180.         n3f(norm);
  181.         T2F(t2);
  182.         v3f(dquad[0]);
  183.         T2F(t2+3);
  184.         v3f(dquad[1]);
  185.         T2F(t2+6);
  186.         v3f(dquad[2]);
  187.         T2F(t2+9);
  188.         v3f(dquad[3]);
  189.     endpolygon();
  190.  
  191. #if NOTEXTURE
  192.     bgnline();
  193.        v3f(dquad[0]);
  194.        v3f(norm_d);
  195.     endline();
  196. #endif
  197. }
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.     There were two stumbling blocks for me, using the smoke utility: 
  205.  
  206.     1) finding out how to properly setup the texture mapping properties 
  207.        and the texture environment.
  208.  
  209.     So, with a little help from some 4Dgifts code that worked...
  210.  
  211.  
  212. /*
  213.  * Parameters for texturing.
  214.  */
  215.  float texps[] =
  216.   {  TX_MAGFILTER, TX_BILINEAR,
  217.      TX_MINFILTER, TX_MIPMAP_BILINEAR,
  218.      TX_WRAP_S, TX_CLAMP,
  219.      TX_WRAP_T, TX_CLAMP,
  220.      TX_NULL
  221.   };
  222.  
  223.  float tevps[] = {TV_MODULATE,TV_NULL};
  224.  
  225.  
  226.     2) Determining what values to use for afunction(), blendfunc(), and 
  227.        zwritemask():
  228.  
  229.     Thanks to the Performer source tree, i was able to construct the 
  230.     following:
  231.    
  232. void uDrawSmokes(uVec3 eye)
  233. {
  234.     long        i, n;
  235.  
  236.  
  237.     zwritemask(0x00000000);
  238.     if (UGET_GFX_TYPE() & PFGFX_HPC_40NS)   /*express gfx*/
  239.        afunction(0,AF_NOTEQUAL);
  240.     else
  241.        afunction(40,AF_GREATER);
  242.  
  243.     blendfunction(BF_SA, BF_MSA);
  244.  
  245.     n = smokeCount;
  246.     for(i=0; i<n; i++) {
  247.         if(smokeList[i]->mode != USMOKE_STOP) {
  248.             drawSmoke(smokeList[i], eye);
  249.         }
  250.     }
  251.  
  252.     blendfunction(BF_ONE, BF_ZERO);
  253.     zwritemask(0xffffffff);
  254.  
  255. }
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.     Creating the textures for stand-alone 'smoke' was alot easier than 
  263.     trying to do it through the full-blown performer interface:
  264.  
  265.     in uTex.c...
  266.  
  267. long uLoadTexFile(uTexture *tex, char *name)
  268. {
  269.     IMAGE          *image_in;
  270.     char            path[_MAXSTRING];
  271.     long            ret;
  272.  
  273.     if(tex == NULL)
  274.     {
  275.         fprintf(stderr,"uLoadTexFile() Null uTexture.\n");
  276.         return -1;
  277.     }
  278.     if(!uFindFile(name, path, R_OK))
  279.     {
  280.       fprintf(stderr,"uLoadTexFile: could not find image file %s\n",name);
  281.       return FALSE;
  282.     }
  283.     if ((image_in = iopen(path, "r")) == NULL)
  284.     {
  285.       fprintf(stderr,"uLoadTexFile: could not load image %s\n", name);
  286.       return FALSE;
  287.     }
  288.  
  289.     ret = uBuildTex(tex, name, image_in);
  290.  
  291.     iclose(image_in);
  292.     return ret;
  293. }
  294.  
  295. in main.c...
  296. void add_fire_tex(void)
  297. {
  298.     fireTex = uNewTex();
  299.     uLoadTexFile(fireTex, "fire.texture");
  300.  
  301.     texdef2d(fireTex->index,fireTex->comp,fireTex->sx,fireTex->sy,
  302.              (unsigned long *)fireTex->image,0,texps);
  303. }
  304.  
  305. void inittex(void)
  306. {
  307.     smokeTex = uNewTex();
  308.     uLoadTexFile(smokeTex, "smoke.texture");
  309.  
  310.     texdef2d(smokeTex->index,smokeTex->comp,smokeTex->sx,smokeTex->sy,
  311.              (unsigned long *)smokeTex->image,0,texps);
  312.  
  313.     add_fire_tex();
  314.  
  315.     tevdef(1,2,tevps);
  316.     tevbind(0,1);
  317. }
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.